package cn.topevery.garden.dal.logic;

import cn.hutool.core.bean.BeanUtil;
import cn.topevery.garden.dal.dao.GreLandDao;
import cn.topevery.garden.dal.util.ExcelImportUtil;
import cn.topevery.garden.entity.po.GreLand;
import cn.topevery.garden.entity.query.GreLandQuery;
import cn.topevery.garden.entity.vo.*;
import cn.topevery.garden.framework.base.BaseLogic;
import hw.topevery.basis.dal.logic.SysClassLogic;
import hw.topevery.basis.dal.util.SysMapTreeUtil;
import hw.topevery.basis.entity.dto.ClassTree;
import hw.topevery.basis.runtime.UserRuntime;
import hw.topevery.framework.GeometryHelper;
import hw.topevery.framework.TreeNode;
import hw.topevery.framework.db.base.BaseEntityDao;
import hw.topevery.framework.db.entity.DataPager;
import hw.topevery.framework.web.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.locationtech.jts.geom.Geometry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Predicate;

/**
 * @author code-generate
 * @date 2022-01-05
 */
@Service
public class GreLandLogic extends BaseLogic<GreLand> {
    @Autowired
    GreLandDao greLandDao;


    public BaseEntityDao<GreLand, Integer> getDao() {
        return greLandDao;
    }


    /**
     * 获取列表
     *
     * @param query
     */
    public DataPager<GreLandVO> listPage(GreLandQuery query) {
        return greLandDao.listPage(query);
    }

    public DataPager<GreLandRecordVO> getRecordList(GreLandQuery query) {
        return greLandDao.getRecordList(query);
    }

    /**
     * 根据自增id批量删除
     *
     * @param ids
     */
    public void deleteBatchById(String userId, Integer[] ids) {
        greLandDao.delete(userId, ids);
    }

    /**
     * 根据自增id保存或者更新
     *
     * @param greLand 实体
     */
    public void saveOrUpdate(String userId, GreLand greLand) {
        greLandDao.saveOrUpdate(userId, greLand);
    }

    /**
     * 根据自定义列值来获取对象
     */
    public GreLand getEntityByColumn(String key, String value) {
        return greLandDao.getEntityByColumn(key, value);
    }

    public GreLandVO getGreLandById(Integer id) {
        return greLandDao.getGreLandById(id);
    }

    public List<Map<String, Object>> getShortList(String deptId) {
        return greLandDao.getShortList(deptId);
    }

    public void commit(GreLandVO vo, Integer userId) {
        greLandDao.commit(vo, userId);
    }

    public boolean isExist(String code) {
        return greLandDao.isExist(code);
    }


    public List<Map<String, Object>> getCityAreaCoveragePercent(LocalDate beginDate, LocalDate endDate, String mapId) {
        return greLandDao.getCityAreaCoveragePercent(beginDate, endDate, mapId);
    }


    public List<CoveragePercentVO> getCoveragePercent() {
        LocalDate endDate = LocalDate.now();
        LocalDate beginDate = endDate.minusYears(2).with(TemporalAdjusters.firstDayOfYear());
        return greLandDao.getCoveragePercentByDate(beginDate, endDate);
    }


    public Map<String, Object> getCitySumAreaCompareInfoByDate(String date) {
        return greLandDao.getCitySumAreaCompareInfoByDate(date);
    }


    public Map<String, Object> getSituation() {
        return greLandDao.getSituation();
    }


    public Map<String, Object> getSituationShow() {
        return greLandDao.getSituationShow();
    }


    public Map<String, Object> getParkSituation() {
        return greLandDao.getParkSituation();
    }


    public Map<String, Object> getParkSituationShow() {
        return greLandDao.getParkSituationShow();
    }


    public List<Map<String, Object>> getAreaStat() {
        return greLandDao.getAreaStat();
    }

    public Map<String, Object> getDataByBoundResource(GreLandQuery query) {
        return greLandDao.getDataByBoundResource(query);
    }

    public DataPager<GreLandInDeptVO> getGreLandInDept(GreLandQuery query) {
        return greLandDao.getGreLandInDept(query);
    }

    public List<GreLand> getServiceAreaGreLandList() {
        return greLandDao.getServiceAreaGreLandList();
    }

    public DataPager<Map<String, Object>> getList(GreLandQuery query) {
        return greLandDao.getList(query);
    }

    public void deleteByIds(List<String> ids, Integer userId) {
        greLandDao.deleteByIds(ids, userId);
    }

    public void updateBySql(GreLand greLand) {
        greLandDao.updateBySql(greLand);
    }

    public void dataPublics(List<Integer> ids, Integer userId) {
        greLandDao.dataPublics(ids, userId);
    }

    public List<Map<String, Object>> getSurvey() {
        return greLandDao.getSurvey();
    }

    public void uptSurvery(String id, String geom_text) {
        greLandDao.uptSurvery(id, geom_text);
    }

    public void updateLand(String id, String geom_text) {
        greLandDao.updateLand(id, geom_text);
    }

    public List<GreLand> getNewUpdateGre(Map<String, String> map) {
        return greLandDao.getNewUpdateGre(map);
    }

    public void updateGreServiceArea(GreLand greLand) {
        greLandDao.updateGreServiceArea(greLand);
    }

    public void insertSql(GreLandVO greLand) {
        greLandDao.insertSql(greLand);
    }

    public String getCode(String mapId, String classId) {
        return greLandDao.getCode(mapId, classId);
    }

    public String getNewcode(String mapId, String classId) {
        return greLandDao.getNewcode(mapId, classId);
    }

    public List<GardenServiceRadiusVO> getGardenServiceRadius() {
        return greLandDao.getGardenServiceRadius();
    }

    public List<Map<String, Object>> getLandAndParkCount() {
        return greLandDao.getLandAndParkCount();
    }

    public Geometry getGeoBuffer(String orgMkt, double distance) {
        return greLandDao.getGeoBuffer(orgMkt, distance);
    }

    public List<Geometry> getAllGeoRadius() {
        return greLandDao.getAllGeoRadius();
    }

    public JsonResult<?> analysisExcel(MultipartFile file) {
        try {
            Map<String, Object> map = ExcelImportUtil.analysisExcel(file.getInputStream(), GreLandVO.class, filterFunc());
            return JsonResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResult.error("解析发生错误，请按照模板格式填写数据！");
        }
    }

    @Autowired
    private SysMapTreeUtil sysMapTreeUtil;

    @Autowired
    private SysClassLogic sysClassLogic;

    private Predicate<GreLandVO> filterFunc() {
        return vo -> {
            if (StringUtils.isBlank(vo.getCode()) || StringUtils.isBlank(vo.getGreeClass()) ||
                    vo.getMeasure() == null || StringUtils.isBlank(vo.getBigClassName())) {
                vo.setErrorMessage("编号/名称/面积/绿地大类 不能为空！");
                return true;
            }
            //校验行政区域
            StringBuilder errorMessageBuilder = new StringBuilder();
            boolean areaFlag = ExcelImportUtil.verifyArea(vo, errorMessageBuilder, sysMapTreeUtil);
            //校验绿地类型
            boolean classFlag = false;
            List<ClassTree> greClassTree = sysClassLogic.getClassTree("8c793ae3-8e14-48e7-aba6-8367cc3f0037");
            if (!CollectionUtils.isEmpty(greClassTree)) {
                Optional<ClassTree> classTreeOption1 = greClassTree.stream().filter(f -> f.getLabel().equals(vo.getBigClassName())).findFirst();
                if (classTreeOption1.isPresent()) {
                    ClassTree classTree1 = classTreeOption1.get();
                    vo.setBigClassId(classTree1.getId());//补充大类id
                    if (StringUtils.isNotBlank(vo.getMediumClassName())) {
                        List<TreeNode> children = classTree1.getChildren();
                        if (CollectionUtils.isEmpty(children)) {
                            classFlag = true;
                            errorMessageBuilder.append("绿地中类不存在！");
                        } else {
                            Optional<TreeNode> classTreeOption2 = children.stream().filter(f -> f.getLabel().equals(vo.getMediumClassName())).findFirst();
                            if (classTreeOption2.isPresent()) {
                                TreeNode treeNode2 = classTreeOption2.get();
                                vo.setMediumClassId(treeNode2.getId());//补充中类id
                                List<TreeNode> children2 = treeNode2.getChildren();
                                if (StringUtils.isNotBlank(vo.getSmallClassName())) {
                                    if (CollectionUtils.isEmpty(children2)) {
                                        classFlag = true;
                                        errorMessageBuilder.append("绿地小类不存在！");
                                    } else {
                                        Optional<TreeNode> classTreeOption3 = children2.stream().filter(f -> f.getLabel().equals(vo.getSmallClassName())).findFirst();
                                        if (classTreeOption3.isPresent()) {
                                            TreeNode treeNode3 = classTreeOption3.get();
                                            vo.setSmallClassId(treeNode3.getId());
                                        } else {
                                            classFlag = true;
                                            errorMessageBuilder.append("绿地小类不存在！");
                                        }
                                    }
                                }
                            } else {
                                classFlag = true;
                                errorMessageBuilder.append("绿地中类不存在！");
                            }
                        }
                    }
                } else {
                    classFlag = true;
                    errorMessageBuilder.append("绿地大类不存在！");
                }
            }
            vo.setType(StringUtils.isNotBlank(vo.getSmallClassId()) ? vo.getSmallClassId() :
                    StringUtils.isNotBlank(vo.getMediumClassId()) ? vo.getSmallClassId() :
                            StringUtils.isNotBlank(vo.getBigClassId()) ? vo.getBigClassId() : null);
            if (StringUtils.isNotBlank(vo.getGeoWkt())) {
                Geometry geometry = GeometryHelper.getGeometry(vo.getGeoWkt());//检查坐标格式是否正常
            }
            vo.setErrorMessage(errorMessageBuilder.toString());
            return areaFlag || classFlag;
        };
    }

    public JsonResult<?> importExcel(List<GreLandVO> greLandVOList) {
        return ExcelImportUtil.importExcel(greLandVOList, filterFunc(), vo -> {
                    GreLand greLand = BeanUtil.copyProperties(vo, GreLand.class);
                    if (StringUtils.isNotBlank(vo.getGeoWkt())) {
                        Geometry geometry = GeometryHelper.getGeometry(vo.getGeoWkt());
                        greLand.setMapRanges(geometry);
                    }
                    greLand.setLandId(UUID.randomUUID().toString());
                    return greLand;
                },
                entities -> greLandDao.insert(UserRuntime.getSysUser().id.toString(), entities));
    }
}
